package com.wngbms.netty._02http.client;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.conn.DnsResolver;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.impl.conn.SystemDefaultDnsResolver;
import org.apache.http.pool.PoolStats;
import org.apache.http.protocol.HttpContext;

import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Slf4j
public class HttpClientHelper {

    static PoolingHttpClientConnectionManager httpClientConnectionManager;
    static CloseableHttpClient closeableHttpClient;

    static {
        log.info("init......");
        httpClientConnectionManager = createHttpClientConnectionManager();

        RequestConfig.Builder builder = RequestConfig.custom();
        // 读取数据的超时时间
        builder.setSocketTimeout(2000);
        // 建立链接的超时时间
        builder.setConnectTimeout(2000);
        // 从连接池获取连接的等待超时时间
        builder.setConnectionRequestTimeout(2000);
        RequestConfig build = builder.build();

        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        httpClientBuilder.setConnectionManager(httpClientConnectionManager);
        httpClientBuilder.setDefaultRequestConfig(build);
        httpClientBuilder.setKeepAliveStrategy(new ConnectionKeepAliveStrategy() {
            @Override
            public long getKeepAliveDuration(HttpResponse httpResponse, HttpContext httpContext) {

                return 0;
            }
        });

        CloseableHttpClient closeableHttpClient = httpClientBuilder.build();
        HttpClientHelper.closeableHttpClient = closeableHttpClient;

        startExpiredConnectionsMonitor();
    }

    public static void startExpiredConnectionsMonitor() {
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(10);
        executorService.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                httpClientConnectionManager.closeExpiredConnections();
                httpClientConnectionManager.closeIdleConnections(60, TimeUnit.SECONDS);

                PoolStats totalStats = httpClientConnectionManager.getTotalStats();
                log.info("status:{}", totalStats);
            }
        }, 2000, 2000, TimeUnit.MILLISECONDS);
    }

    public static PoolingHttpClientConnectionManager createHttpClientConnectionManager() {
        DnsResolver dnsResolver = SystemDefaultDnsResolver.INSTANCE;
        // http
        ConnectionSocketFactory plainSocketFactory
                = PlainConnectionSocketFactory.getSocketFactory();
        // https
        LayeredConnectionSocketFactory sslSocketFactory
                = SSLConnectionSocketFactory.getSocketFactory();

        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", plainSocketFactory)
                .register("https", sslSocketFactory)
                .build();

        PoolingHttpClientConnectionManager httpClientConnectionManager
                = new PoolingHttpClientConnectionManager(registry,
                null, null,
                dnsResolver, 15, TimeUnit.SECONDS);
        httpClientConnectionManager.setValidateAfterInactivity(2000);
        httpClientConnectionManager.setMaxTotal(5);
        httpClientConnectionManager.setDefaultMaxPerRoute(3);
        return httpClientConnectionManager;
    }

}
